/***************************************************************************
 *   Copyleft 2008-2009 by												   *
 *	 Iwanicki Krzysztof													   *
 *   <gamma.mini.pw.edu.pl/~iwanickik>									   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 ***************************************************************************/
#ifndef __VXMLOUTPUTSTREAM_H__
#define __VXMLOUTPUTSTREAM_H__

#include "../../Utils/vUtils.h"
#include "./TinyXML/tinyxml.h"
#include "../../Macros/vMemoryMacros.h"

namespace Vendetta {
	/*! \class vXmlOutputStream
	 *   \brief A vXmlOutputStream abstract class manages saving data to xml files.
	 *
	 *	vXmlOutputStream use TinyXML parser for parsing .xml files. 
	 *	TinyXML can be found at http://www.grinninglizard.com/tinyxml
	 *
	 *	\sa TinyXML.
	 */
	class vXmlOutputStream {
	public:
		/*! \brief Default constructor.
		 *
		 */	
		vXmlOutputStream(): mBoolWriteType(vStringConverter::VBT_TRUEFALSE_C) { }

		/*! \brief Destructor.
		 *
		 */	
		virtual ~vXmlOutputStream() { }


		/*! \brief Writes data to xml file.
		 *
		 *	Calls init to prepare data for saving on hard drive. All preparations to TiXmlDocument
		 *	should be made in init.
		 *			 
		 *  \param		fileName	File name in which data should be serialized.
		 *	\return					True if data was successfully saved, false otherwise.
		 *	\sa			TinyXML.
		 */
		virtual vBool SaveToFile(const vString& fileName);

	protected:
		/*! \brief Pure virtual method. Is called before saving data to file.
		 *
		 *	\return					True if data was successfully saved, false otherwise.
		 *
		 */
		virtual vBool preSave() = 0;

		/*! \brief Sets how to write bool type to file.
		 *
		 *	\param		boolType	Bool format.
		 *	\sa			vStringConverter::eBoolType.
		 */
		vVoid setBoolWriteType(vStringConverter::eBoolType boolType);

		/*! \brief Opens new tag with given name.
		 *
		 *	Opened tag is the current tag to work on. When finished defining new tag,
		 *	use closeLastOpenedTagForWrite to close all tags and clean memory.
		 *
		 *	\param		tagName		Tag name.
		 *	\sa			vXmlOutputStream::closeLastOpenedTagForWrite.
		 */
		vVoid openTagForWrite(const vString& tagName);

		/*! \brief Closes last opened tag. Tag is in open mode after call to openTagForWrite.
		 *
		 *	\sa			vXmlOutputStream::openTagForWrite.
		 */
		vVoid closeLastOpenedTagForWrite();

		/*! \brief Closes all opened tag. Tag is in open mode after call to openTagForWrite.
		 *
		 *	\sa			vXmlOutputStream::openTagForWrite.
		 */
		vVoid closeRemainingTagsForWrite();

		/*! \brief Adds new attribute with given name to current opened tag.
		 *
		 *	\param		attName		Attribute name.
		 *	\param		val			Attribute value.
		 *	\exception	vException	Thrown when no tag is opened.
		 *	\sa			vString.
		 */
		vXmlOutputStream& addAtribute(const vString& attName, const vString& val);

		/*! \brief Adds new attribute with given name to current opened tag. Overloaded.
		 *
		 *	\param		attName		Attribute name.
		 *	\param		val			Attribute value.
		 *	\exception	vException	Thrown when no tag is opened.
		 *	\sa			vString.
		 */
		vXmlOutputStream& addAtribute(const vString& attName, vInt val);

		/*! \brief Adds new attribute with given name to current opened tag. Overloaded.
		 *
		 *	\param		attName		Attribute name.
		 *	\param		val			Attribute value.
		 *	\exception	vException	Thrown when no tag is opened.
		 *	\sa			vString.
		 */
		vXmlOutputStream& addAtribute(const vString& attName, vUInt val);

		/*! \brief Adds new attribute with given name to current opened tag. Overloaded.
		 *
		 *	\param		attName		Attribute name.
		 *	\param		val			Attribute value.
		 *	\exception	vException	Thrown when no tag is opened.
		 *	\sa			vString.
		 */
		vXmlOutputStream& addAtribute(const vString& attName, vUInt32 val);

		/*! \brief Adds new attribute with given name to current opened tag. Overloaded.
		 *
		 *	\param		attName		Attribute name.
		 *	\param		val			Attribute value.
		 *	\exception	vException	Thrown when no tag is opened.
		 *	\sa			vString.
		 */
		vXmlOutputStream& addAtribute(const vString& attName, vReal val);

		/*! \brief Adds new attribute with given name to current opened tag. Overloaded.
		 *
		 *	\param		attName		Attribute name.
		 *	\param		val			Attribute value.
		 *	\exception	vException	Thrown when no tag is opened.
		 *	\sa			vString.
		 */
		vXmlOutputStream& addAtribute(const vString& attName, vChar val);

		/*! \brief Adds new attribute with given name to current opened tag. Overloaded.
		 *
		 *	\param		attName		Attribute name.
		 *	\param		val			Attribute value.
		 *	\exception	vException	Thrown when no tag is opened.
		 *	\sa			vString.
		 */
		vXmlOutputStream& addAtribute(const vString& attName, vBool val);

		/*! \brief Adds new attribute with given name to current opened tag. Overloaded.
		 *
		 *	\param		attName		Attribute name.
		 *	\param		val			Attribute value.
		 *	\exception	vException	Thrown when no tag is opened.
		 *	\sa			vString.
		 */
		vXmlOutputStream& addAtribute(const vString& attName, vLong val);

		/*! \brief Adds text to current opened tag.
		 *
		 *	\param		text		Text to add.
		 *	\exception	vException	Thrown when no tag is opened.
		 *	\sa			vString.
		 */
		vXmlOutputStream& addText(const vString& text);

		/*! \brief Adds text tag as child to current opened tag.
		 *
		 *	\param		tagName		Tag name.
		 *	\param		text		Text to add.
		 *	\exception	vException	Thrown when no tag is opened.
		 *	\sa			vString.
		 */
		vXmlOutputStream& addTextTag(const vString& tagName, const vString& text);


	protected:
		//!	TiXmlDocument object. Refer to TiXml documentation.
		TiXmlDocument mDocTag;


	private:
		vStringConverter::eBoolType mBoolWriteType;
		vStack<TiXmlElement*> mTags;

	};
}


#endif // __VXMLOUTPUTSTREAM_H__